﻿using System;
using System.Collections.Generic;
using System.IO;
using GeoAPI.Geometries;

namespace NetTopologySuite.GeometriesGraph
{
	public class NodeMap
	{
		public NodeMap(NodeFactory nodeFact)
		{
			this._nodeFact = nodeFact;
		}

		public Node AddNode(Coordinate coord)
		{
			Node node;
			if (!this._nodeMap.TryGetValue(coord, out node))
			{
				node = this._nodeFact.CreateNode(coord);
				this._nodeMap.Add(coord, node);
			}
			return node;
		}

		public Node AddNode(Node n)
		{
			Node node = this._nodeMap[n.Coordinate];
			if (node == null)
			{
				this._nodeMap.Add(n.Coordinate, n);
				return n;
			}
			node.MergeLabel(n);
			return node;
		}

		public void Add(EdgeEnd e)
		{
			Coordinate coordinate = e.Coordinate;
			this.AddNode(coordinate).Add(e);
		}

		public Node Find(Coordinate coord)
		{
			Node result;
			if (!this._nodeMap.TryGetValue(coord, out result))
			{
				return null;
			}
			return result;
		}

		public IEnumerator<Node> GetEnumerator()
		{
			return this._nodeMap.Values.GetEnumerator();
		}

		public IList<Node> Values
		{
			get
			{
				return new List<Node>(this._nodeMap.Values);
			}
		}

		public IList<Node> GetBoundaryNodes(int geomIndex)
		{
			IList<Node> list = new List<Node>();
			foreach (Node node in this._nodeMap.Values)
			{
				if (node.Label.GetLocation(geomIndex) == Location.Boundary)
				{
					list.Add(node);
				}
			}
			return list;
		}

		public void Write(StreamWriter outstream)
		{
			foreach (Node node in this._nodeMap.Values)
			{
				node.Write(outstream);
			}
		}

		private readonly IDictionary<Coordinate, Node> _nodeMap = new SortedDictionary<Coordinate, Node>();

		private readonly NodeFactory _nodeFact;
	}
}
